package fieldmaps.voronoi.delaunayLibrary;

/*
 * Copyright (c) 2005, 2007 by L. Paul Chew.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
import javax.vecmath.Point2d;

import org.apache.log4j.Logger;

/**
 * The Delauany applet.
 * 
 * Creates and displays a Delaunay Triangulation (DT) or a Voronoi Diagram
 * (VoD). Has a main program so it is an application as well as an applet.
 * 
 * @author Paul Chew
 * 
 *         Created July 2005. Derived from an earlier, messier version.
 * 
 *         Modified December 2007. Updated some of the Triangulation methods.
 *         Added the "Colorful" checkbox. Reorganized the interface between
 *         DelaunayAp and DelaunayPanel. Added code to find a Voronoi cell.
 * 
 */
@SuppressWarnings("serial")
public class DelaunayAp extends javax.swing.JApplet implements Runnable,
		ActionListener, MouseListener {

	private final static Logger LOGGER = Logger.getLogger(DelaunayAp.class);
	
	private boolean debug = false;
	private Component currentSwitch = null;

	private static String windowTitle = "Voronoi/Delaunay Window";
	private JRadioButton voronoiButton = new JRadioButton("Voronoi Diagram");
	private JRadioButton delaunayButton = new JRadioButton(
			"Delaunay Triangulation");
	private JButton clearButton = new JButton("Clear");
	private JCheckBox colorfulBox = new JCheckBox("More Colorful");
	private DelaunayPanel delaunayPanel = new DelaunayPanel(this);
	private JLabel circleSwitch = new JLabel("Show Empty Circles");
	private JLabel delaunaySwitch = new JLabel("Show Delaunay Edges");
	private JLabel voronoiSwitch = new JLabel("Show Voronoi Edges");

	/**
	 * Main program (used when run as application instead of applet).
	 */
	public static void main(String[] args) {
		double X_size = 700;
		double Y_size = 500;
		
		DelaunayAp applet = new DelaunayAp(); // Create applet
		applet.init(); // Applet initialization
		JFrame dWindow = new JFrame(); // Create window
		dWindow.setSize((int) X_size, (int) Y_size); // Set window size
		dWindow.setTitle(windowTitle); // Set window title
		dWindow.setLayout(new BorderLayout()); // Specify layout manager
		dWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// Specify closing behavior
		dWindow.add(applet, "Center"); // Place applet into window
		dWindow.setVisible(true); // Show the window
	}

	/**
	 * Initialize the applet. As recommended, the actual use of Swing components
	 * takes place in the event-dispatching thread.
	 */
	public void init() {
		try {
			SwingUtilities.invokeAndWait(this);
		} catch (Exception e) {
			System.err.println("Initialization failure");
		}
	}

	/**
	 * Set up the applet's GUI. As recommended, the init method executes this in
	 * the event-dispatching thread.
	 */
	public void run() {
		setLayout(new BorderLayout());

		// Add the button controls
		ButtonGroup group = new ButtonGroup();
		group.add(voronoiButton);
		group.add(delaunayButton);
		JPanel buttonPanel = new JPanel();
		buttonPanel.add(voronoiButton);
		buttonPanel.add(delaunayButton);
		buttonPanel.add(clearButton);
		buttonPanel.add(new JLabel("          "));
		buttonPanel.add(colorfulBox);
		this.add(buttonPanel, "North");

		// Add the mouse-entry switches
		JPanel switchPanel = new JPanel();
		switchPanel.add(circleSwitch);
		switchPanel.add(new Label("     ")); // Spacing
		switchPanel.add(delaunaySwitch);
		switchPanel.add(new Label("     ")); // Spacing
		switchPanel.add(voronoiSwitch);
		this.add(switchPanel, "South");

		// Build the delaunay panel
		getDelaunayPanel().setBackground(Color.gray);
		this.add(getDelaunayPanel(), "Center");

		// Register the listeners
		voronoiButton.addActionListener(this);
		delaunayButton.addActionListener(this);
		clearButton.addActionListener(this);
		colorfulBox.addActionListener(this);
		getDelaunayPanel().addMouseListener(this);
		circleSwitch.addMouseListener(this);
		delaunaySwitch.addMouseListener(this);
		voronoiSwitch.addMouseListener(this);

		// Initialize the radio buttons
		voronoiButton.doClick();
	}

	/**
	 * A button has been pressed; redraw the picture.
	 */
	public void actionPerformed(ActionEvent e) {
		if (debug)
			System.out.println(((AbstractButton) e.getSource()).getText());
		if (e.getSource() == clearButton)
			getDelaunayPanel().clear();
		getDelaunayPanel().repaint();
	}

	/**
	 * If entering a mouse-entry switch then redraw the picture.
	 */
	public void mouseEntered(MouseEvent e) {
		currentSwitch = e.getComponent();
		if (currentSwitch instanceof JLabel)
			getDelaunayPanel().repaint();
		else
			currentSwitch = null;
	}

	/**
	 * If exiting a mouse-entry switch then redraw the picture.
	 */
	public void mouseExited(MouseEvent e) {
		currentSwitch = null;
		if (e.getComponent() instanceof JLabel)
			getDelaunayPanel().repaint();
	}

	/**
	 * If mouse has been pressed inside the delaunayPanel then add a new site.
	 */
	public void mousePressed(MouseEvent e) {
		if (e.getSource() != getDelaunayPanel())
			return;
		Pnt point = new Pnt(e.getX(), e.getY());
		if (debug)
			System.out.println("Click " + point);
		getDelaunayPanel().addSite(point);
		getDelaunayPanel().repaint();
	}

	/**
	 * Draw a list of points
	 */
	public void addPoints(List<Point2d> points) {
		if (points == null || points.isEmpty())
			return;
		for (Point2d point2d : points) {
			Pnt point = new Pnt(point2d.x, point2d.y);
			getDelaunayPanel().addSite(point);
		}
		getDelaunayPanel().repaint();
	}

	/**
	 * Not used, but needed for MouseListener.
	 */
	public void mouseReleased(MouseEvent e) {
	}

	public void mouseClicked(MouseEvent e) {
	}

	/**
	 * @return true iff the "colorful" box is selected
	 */
	public boolean isColorful() {
		return colorfulBox.isSelected();
	}

	/**
	 * @return true iff doing Voronoi diagram.
	 */
	public boolean isVoronoi() {
		return voronoiButton.isSelected();
	}

	/**
	 * @return true iff within circle switch
	 */
	public boolean showingCircles() {
		return currentSwitch == circleSwitch;
	}

	/**
	 * @return true iff within delaunay switch
	 */
	public boolean showingDelaunay() {
		return currentSwitch == delaunaySwitch;
	}

	/**
	 * @return true iff within voronoi switch
	 */
	public boolean showingVoronoi() {
		return currentSwitch == voronoiSwitch;
	}

	public void setDelaunayPanel(DelaunayPanel delaunayPanel) {
		this.delaunayPanel = delaunayPanel;
	}

	public DelaunayPanel getDelaunayPanel() {
		return delaunayPanel;
	}
}
